package _08_DFS_BFS;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class _47_全排列_II复习 {

    private List<List<Integer>> results = new ArrayList<>();


    public List<List<Integer>> permuteUnique(int[] nums) {
        // 数组排序，去重
        Arrays.sort(nums);
        boolean[] visited = new boolean[nums.length];
        int[] list = new int[nums.length];
        dfs(0, nums, list, visited);
        return results;
    }

    private void dfs(int deep, int[] nums, int[] list, boolean[] visited) {
        if (deep == nums.length) {
            ArrayList<Integer> temp = new ArrayList<>();
            for (int j : list) {
                temp.add(j);
            }
            results.add(temp);
            return;
        }

        for (int i = 0; i < nums.length; i++) {
            // 如果前一个等于，后一个，并且前一个没有被访问
            if (visited[i] || (i > 0 && nums[i] == nums[i - 1] && !visited[i - 1])) continue;
            // 去重
            visited[i] = true;
            list[deep] = nums[i];
            dfs(deep + 1, nums, list, visited);
            visited[i] = false;
        }
    }


    // 使用替换策略
    public List<List<Integer>> permuteUnique1(int[] nums) {
        // 数组进行排序操作
        dfs1(0, nums);
        return results;
    }

    // 采用交换策略
    private void dfs1(int i, int[] nums) {
        if (i == nums.length) {
            List<Integer> temp = new ArrayList<>();
            for (int j = 0; j < nums.length; j++) {
                temp.add(nums[i]);
            }
            results.add(temp);
            return;
        }

        for (int j = i; j < nums.length; j++) {
            if (isRepeat(nums, i, j)) continue;
            if (i == j) {
                dfs1(i + 1, nums);
            } else {
                swap(nums, i, j);
                dfs1(i + 1, nums);
                // 回溯
                swap(nums, i, j);
            }
        }
    }

    private boolean isRepeat(int[] nums, int i, int j) {
        for (int k = i; k < j; k++) {
            if (nums[k] == nums[j]) return true;
        }
        return false;
    }

    public void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }

}
